package com.tarena.lbs.basic.web.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.web.repository.AdminRepository;
import com.tarena.lbs.basic.web.repository.BusinessRepository;
import com.tarena.lbs.basic.web.utils.AuthenticationContextUtils;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.dto.AdminDTO;
import com.tarena.lbs.pojo.basic.param.AdminParam;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.BusinessPO;
import com.tarena.lbs.pojo.basic.query.AdminQuery;
import com.tarena.lbs.pojo.basic.vo.AdminVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AdminService {
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private BusinessRepository businessRepository;

    public AdminVO detail() throws BusinessException {
        //在过滤器 存储了上游线程的参数 当前请求的认证对象
        //service作为过滤器的下游处理逻辑,使用同一个线程执行代码 当然可以从threadLocal读数据
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        //过滤器 并没有保证能解析成功userPrinciple
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证解析失败"));
        Integer adminId=userPrinciple.getId();
        AdminPO po = adminRepository.getById(adminId);
        AdminVO vo=new AdminVO();
        BeanUtils.copyProperties(po,vo);
        return vo;
    }
    public AdminDTO detail(Integer adminId){
        AdminPO po = adminRepository.getById(adminId);
        AdminDTO dto=null;
        if(po!=null){
            dto=new AdminDTO();
            BeanUtils.copyProperties(po,dto);
        }
        return dto;
    }

    public PageResult<AdminVO> pageList(AdminQuery query) {
        //1.准备一个 返回值 PageResult
        PageResult<AdminVO> voPage=new PageResult<>(query.getPageSize(),query.getPageNo());
        //2.给pageResult封装4个属性 pageNo pageSize 入参 total list 分页查询查询 pageInfo 转化vo
        //2.1调用仓储层 获取pageInfo
        PageInfo<AdminPO> pageInfo= getPageAdmin(query);
        //2.2将pageInfo的total交给pageResult使用
        voPage.setTotal(pageInfo.getTotal());
        //2.3 判断非空 在转化vos
        List<AdminPO> pos = pageInfo.getList();
        List<AdminVO> vos=null;
        if (pos!=null&& pos.size()>0){
            vos=pos.stream().map(po->{
                AdminVO vo=new AdminVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    private PageInfo<AdminPO> getPageAdmin(AdminQuery query) {
        //应该使用query中 accountPhone和nickname 业务参数拼接查询条件
        //开启分页
        PageHelper.startPage(query.getPageNo(), query.getPageSize());
        //理解查询列表
        List<AdminPO> pos = adminRepository.list();//没有参数查询所有
        //封装pageInfo返回
        return new PageInfo<>(pos);
    }

    public void addAdmin(AdminParam param) throws BusinessException {
        //1.检查角色 是否符合当前业务功能的要求
        checkRole(Roles.ADMIN);
        //2.验证 参数传递businessId是否合法 存在
        checkBusiness(param.getBusinessId());
        //3.检查是否存在电话号码相同的商家账号
        checkPhoneReuse(param.getAccountPhone());
        //4.param数据转化成 po 写入数据库
        AdminPO poParam=param2po(param);
        adminRepository.save(poParam);
    }

    private AdminPO param2po(AdminParam param) {
        //1.能拷贝的 给这个po先拷贝过来
        AdminPO poParam=new AdminPO();
        BeanUtils.copyProperties(param,poParam);
        //2.账号状态 0启用 1禁用
        poParam.setAccountStatus(0);
        //3.账号创建时间
        poParam.setCreateTime(new Date());
        //4.如果账号是商家 businessId有值的,但是如果账号是平台管理员 businessId空的 平台绑定bizId==0
        poParam.setBusinessId(param.getAccountType()==0?0:param.getBusinessId());
        return poParam;
    }

    private void checkPhoneReuse(String accountPhone) throws BusinessException {
        //1.组织一个查询条件 where account_phone=#{phone}
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("account_phone",accountPhone);
        //2.断言 count>0 抛异常
        long count = adminRepository.count(queryWrapper);
        Asserts.isTrue(count>0,new BusinessException("-2","手机号重复使用"));
    }

    private void checkBusiness(Integer businessId) throws BusinessException {
        //使用商家id查询 商家count 如果>0   断言 ==0 抛异常
        BusinessPO po = businessRepository.getById(businessId);
        Asserts.isTrue(po==null,new BusinessException("-2","商家绑定失败"));
    }

    private void checkRole(Roles role) throws BusinessException {
        //当前系统 有一个过滤器 解析jwt 拿到userPrinciple 所有业务功能都在过滤器下游可以获取传参
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        //断言判断 如果认证对象是空 抛出异常
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证解析失败"));
        //从认证对象拿到发起请求的用户 真实角色
        Roles userRole = userPrinciple.getRole();
        //断言 必须要求用户角色 和入参角色相等 ,不相等 抛异常
        Asserts.isTrue(userRole!=role,new BusinessException("-2","新增商家需要平台管理员"));
    }
}
